﻿using CommandSystem;
using Exiled.API.Features;
using Exiled.API.Features.Doors;
using Exiled.API.Features.Roles;
using HarmonyLib;
using MEC;
using Mirror;
using PlayerRoles;
using PlayerStatsSystem;
using RgCore.PlayerHud;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

namespace ScpSwap
{
    public struct MatchInfo
    {
        public float Health { get; set; }

        public Vector3 Position { get; set; }

        public RoleTypeId Role { get; set; }

        public int Scp079Exp { get; set; }

        public int Scp079Level { get; set; }
    }

    public static class ScpReplacement
    {
        public static DateTime launchTime = DateTime.Now;
        public static MatchInfo? Current = null;
        public static List<MatchInfo> Queue = new List<MatchInfo>();
        public static CoroutineHandle coroutine;
        public static Harmony Harmony { get; private set; } = null;

        public static void AddQueue(float health, RoleTypeId role, Vector3 position, int experience, int level)
        {
            if (role == RoleTypeId.Scp079)
            {
                if (!Door.Get("079_SECOND").IsLocked)
                {
                    return;
                }
            }
            Queue.Add(new MatchInfo
            {
                Health = health,
                Role = role,
                Position = position,
                Scp079Exp = experience,
                Scp079Level = level,
            });
        }

        public static void RegisterEvents(bool awake)
        {
            if (awake)
            {
                coroutine = Timing.RunCoroutine(Update());
                Harmony = new Harmony("scp_replacement");
                Harmony.Patch(AccessTools.Method(typeof(CustomNetworkManager), nameof(CustomNetworkManager.OnServerDisconnect)),
                    new HarmonyMethod(typeof(Patches).GetMethod(nameof(Patches.OnServerDisconnect_Prefix))));
            }
            else
            {
                Timing.KillCoroutines(coroutine);
                Harmony.UnpatchAll(Harmony.Id);
            }
        }

        public static IEnumerator<float> Update()
        {
            while (true)
            {
                if (Current == null)
                {
                    if (Queue.Count > 0)
                    {
                        Current = Queue.First();
                        launchTime = DateTime.Now;
                        Queue.RemoveAt(0);
                    }
                }
                else if (launchTime.AddSeconds(15) > DateTime.Now)
                {
                    foreach (Player player in Player.List.Where(x => !x.IsAlive))
                    {
                        if (!player.HasMsg("scp_replacement"))
                        {
                            player.SendRawMsg("scp_replacement", $"[<color=#FF1111>SCP顶替</color>] <color=#DD0040>{Current.Value.Role}</color> 等待顶替 | 输入<color=#FF0000>.rp</color>来顶替", 15, ScreenLocation.Top, false);
                        }
                    }
                }
                else
                {
                    Current = null;
                    HudHandler.DeleteMsg("scp_replacement", true, Player.List.ToArray());
                }
                yield return Timing.WaitForSeconds(1.0f);
            }
        }
    }

    public class ScpReplacementCommand : ICommand
    {
        public string Command => "rp";

        public string[] Aliases => Array.Empty<string>();

        public string Description => string.Empty;

        public bool Execute(ArraySegment<string> arguments, ICommandSender sender, out string response)
        {
            Player player = Player.Get(sender);
            if (ScpReplacement.Current.HasValue && player.Role == RoleTypeId.Spectator)
            {
                var a = ScpReplacement.Current.Value;
                ScpReplacement.Current = null;
                HudHandler.DeleteMsg("scp_replacement", true, Player.List.ToArray());
                player.Role.Set(a.Role);
                Timing.CallDelayed(1f, () =>
                {
                    player.Health = a.Health;
                    if (player.Role == RoleTypeId.Scp079)
                    {
                        (player.Role as Scp079Role).Experience = a.Scp079Exp;
                        (player.Role as Scp079Role).Level = a.Scp079Level;
                    }
                    else
                    {
                        player.Position = a.Position;
                    }
                });
                response = "成功替换为SCP角色";
                return true;
            }
            else
            {
                response = "没有可替换的SCP角色";
                return false;
            }
        }
    }

    public static class Patches
    {
        public static bool OnServerDisconnect_Prefix(CustomNetworkManager __instance, NetworkConnectionToClient conn)
        {
            __instance._disconnectDrop = false;
            if (!Round.IsEnded && conn.identity != null && ReferenceHub.TryGetHubNetID(conn.identity.netId, out ReferenceHub referenceHub))
            {
                Player player = Player.Get(referenceHub);
                if (player.IsScp && player.Role.Type != RoleTypeId.Scp0492)
                {
                    int exp = 0;
                    int lvl = 1;
                    if (player.Role is Scp079Role comp)
                    {
                        exp = comp.Experience;
                        lvl = comp.Level;
                    }
                    ScpReplacement.AddQueue(player.Health, player.Role.Type, player.Position, exp, lvl);
                }
                else
                {
                    referenceHub.playerStats.KillPlayer(new CustomReasonDamageHandler("与服务器断开连接"));
                }
            }
            return true;
        }
    }
}